package com.fzf.org.toolkit;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fzf.org.dao.entities.BasicDO;
import com.fzf.org.dao.entities.UserDO;
import com.fzf.org.exception.BizException;
import com.fzf.org.exception.BizExceptionTypeEnum;

import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.concurrent.ConcurrentHashMap;

import static com.fzf.org.toolkit.ConstantKey.*;

public class JWTAuthenticator {

    public static String generateToken(BasicDO basicDO){
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND, TOKEN_EXPIRE_TIME);// 设置签名过期时间

        return TOKEN_PREFIX + JWT.create()
                .withClaim("userId", basicDO.getId())
                .withClaim("userAccount", basicDO.getAccount())
                .withClaim("userRole", basicDO.getRoleId()) // 签名中包含的数据
                .withExpiresAt(instance.getTime())  // 签名过期时间
                .sign(Algorithm.HMAC512(SECRET_KEY));// 签名算法，要求加密解密必须一致;
    }

    public static BasicDO getBasicFromToken(String token) {
        String jwtToken = token.replace(TOKEN_PREFIX, "");
        try{
            DecodedJWT verify = JWT.require(Algorithm.HMAC512(SECRET_KEY)).build().verify(jwtToken);
            if (verify.getClaim("userId").asLong() == null || verify.getClaim("userAccount").asString() == null || verify.getClaim("userRole").asLong() == null) {
                throw new BizException(BizExceptionTypeEnum.JWT_VERIFY_INFO_ERROR);
            }

            return BasicDO.builder()
                    .id(verify.getClaim("userId").asLong())
                    .account(verify.getClaim("userAccount").asString())
                    .roleId(verify.getClaim("userRole").asLong())
                    .build();
        }catch (Exception e){
            throw new BizException(BizExceptionTypeEnum.JWT_VERIFY_INFO_ERROR);
        }
    }

    public static <T extends BasicDO> T getUserFromToken(String token, Class<T> clazz) {
        String jwtToken = token.replace(TOKEN_PREFIX, "");
        DecodedJWT verify = JWT.require(Algorithm.HMAC512(SECRET_KEY)).build().verify(jwtToken);

        Long userId = verify.getClaim("userId").asLong();
        String account = verify.getClaim("userAccount").asString();
        Long roleId = verify.getClaim("userRole").asLong();

        if (userId == null || account == null || roleId == null) {
            throw new BizException(BizExceptionTypeEnum.JWT_VERIFY_INFO_ERROR);
        }
        try {
            // 获取子类的 Builder
            Method builderMethod = clazz.getMethod("builder");
            Object builder = builderMethod.invoke(null);

            Method idMethod = builder.getClass().getMethod("id", Long.class);
            Method accountMethod = builder.getClass().getMethod("account", String.class);
            Method roleIdMethod = builder.getClass().getMethod("roleId", Long.class);
            Method buildMethod = builder.getClass().getMethod("build");

            idMethod.invoke(builder, userId);
            accountMethod.invoke(builder, account);
            roleIdMethod.invoke(builder, roleId);

            @SuppressWarnings("unchecked")
            T result = (T) buildMethod.invoke(builder);
            return result;
        } catch (Exception e) {
            throw new RuntimeException("Failed to create instance from token", e);
        }
    }

}
